package edu.xlh.travel.service.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.xlh.travel.common.OnlineUserInfoInRedisConstant;
import edu.xlh.travel.common.Result;
import edu.xlh.travel.config.MySessionListener;
import edu.xlh.travel.dao.OnlineUserInfoDao;
import edu.xlh.travel.jwt.filter.JwtFilter;
import edu.xlh.travel.pojo.*;
import edu.xlh.travel.pojo.querypojo.QueryOnlineUserInfo;
import edu.xlh.travel.redis.utils.JedisManager;
import edu.xlh.travel.service.AdminService;
import edu.xlh.travel.service.OnlineUserInfoService;
import edu.xlh.travel.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
@Transactional
public class OnlineUserInfoServiceImpl implements OnlineUserInfoService {
    @Autowired
    private JedisManager jedisManager;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private OnlineUserInfoDao onlineUserInfoDao;

    @Override
    public Result save(HttpServletRequest request , HttpSession session)  {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201);
        }
        String ip = StringUtils.getIp(request);
        String cityInfo = StringUtils.getCityInfo(ip);
        String browser = StringUtils.getBrowser(request);
        //获取当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        OnlineUserInfo onlineUserInfo = new OnlineUserInfo().setId(idWorker.nextId() + "")
                .setName(user.getName())
                .setUserId(user.getId())
                .setLoginedIp(ip)
                .setLoginedAdd(cityInfo)
                .setLoginedBrowser(browser)
                .setLoginedTime(DateTimeUtil.strToDate(date, "yyyy-MM-dd HH:mm:ss"));

        ObjectMapper mapper = new ObjectMapper();
        String onlineUserInfoStr = null;
        try {
            onlineUserInfoStr = mapper.writeValueAsString(onlineUserInfo);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //byte[] serialize = SerializeUtil.serialize(str);
        //存入redis);
        try{
            //版本1
           /* jedisManager.sadd(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES , onlineUserInfoStr);*/
            //版本2
            String userId = user.getId();
            jedisManager.setex(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES+"::"+userId , 600 , onlineUserInfoStr);
        }catch(Exception e) {

        }
        //redisTemplate.boundSetOps(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES.getBytes()).add(serialize);
        //存入数据库
        OnlineUserInfo save = onlineUserInfoDao.save(onlineUserInfo);
        if (save != null) {
            return new Result(200 , "在线用户"+onlineUserInfo.getName()+"入库成功");
        }
        return new Result(202 , "在线用户"+onlineUserInfo.getName()+"入库失败");
    }

    @Override
    public Result findAllOnlineUserInfo(int page, int limit ,HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201);
        }
        //从redis中获取
        //Set <String> onlineUserInfoListInRedis = null;
        List<OnlineUserInfo> OnlineUserInfObjectsList = new ArrayList<>();
        try{
           /* onlineUserInfoListInRedis = jedisManager.
                    smembers(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES);*/
            Set<String> keys = jedisManager.keys(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES+"::*");
            /*for (String key : keys) {
                String value = jedisManager.get(key);
                OnlineUserInfo onlineUserInfo = JSON.parseObject(value, OnlineUserInfo.class);
                OnlineUserInfObjectsList.add(onlineUserInfo);
            }*/
            keys.stream().forEach(key -> {
                String value = jedisManager.get(key);
                OnlineUserInfo onlineUserInfo = JSON.parseObject(value, OnlineUserInfo.class);
                OnlineUserInfObjectsList.add(onlineUserInfo);
            });
        }catch(Exception e) {

        }

       /* List<OnlineUserInfo> OnlineUserInfObjectsList = new ArrayList<>();
        for (String onlineUserInfoString : onlineUserInfoListInRedis) {
            OnlineUserInfo onlineUserInfo = JSON.parseObject(onlineUserInfoString, OnlineUserInfo.class);
            OnlineUserInfObjectsList.add(onlineUserInfo);
        }*/

        if (OnlineUserInfObjectsList != null && OnlineUserInfObjectsList.size() > 0) {
            return new Result(0 ,"从redis返回在线管理员列表成功" ,new PageResult<OnlineUserInfo>((long)OnlineUserInfObjectsList.size(), OnlineUserInfObjectsList));
        }

       /* Sort sort = Sort.by(Sort.Direction.DESC,"loginedTime");
        List<OnlineUserInfo> onlineUserInfoList = onlineUserInfoDao.findAll(sort);
        if (onlineUserInfoList!=null && onlineUserInfoList.size()>0) {
            return new Result(0 , "从数据库返回在线管理员列表成功" ,onlineUserInfoList);
        }*/
        return new Result(202 , "返回在线管理员列表失败或者暂时没有在线管理员登录");
    }

    @Override
    public Integer getOnlineUserCount() {
        Set<String> keys = jedisManager.keys(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES+"::*");
        Integer count = keys.size();
        if (keys != null && count > 0 ) {
            return count;
        }
        return -1;
    }

    @Override
    public Result QueryOnlineUserByCondition(Integer page, Integer limit , QueryOnlineUserInfo queryOnlineUserInfo, HttpSession session) {
        User userFromSession = (User)session.getAttribute("admin");
        if (userFromSession == null) {
            return new Result(201,"会话过期，请重新登陆");
        }

        //解决重置后只能查库而不能查redis问题
        if (StringUtils.isEmpty(queryOnlineUserInfo.getName())
                && StringUtils.isEmpty(queryOnlineUserInfo.getLoginedAdd())
        && StringUtils.isEmpty(queryOnlineUserInfo.getLoginedBrowser())
        && (queryOnlineUserInfo.getLoginedTime() == null)) {
            return findAllOnlineUserInfo(page , limit , session);
        }
        /*if (queryOnlineUserInfo.getLoginedAdd())  {
            findAllOnlineUserInfo(page , limit , session);
        }*/
        Specification<OnlineUserInfo> specification = new Specification<OnlineUserInfo>() {
            @Override
            public Predicate toPredicate(Root<OnlineUserInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> onlineUserList = new ArrayList<>();
                if (!org.springframework.util.StringUtils.isEmpty(queryOnlineUserInfo.getName())) {
                    onlineUserList.add(criteriaBuilder.like(root.get("name") , "%" + queryOnlineUserInfo.getName() + "%"));
                }
                if (!org.springframework.util.StringUtils.isEmpty(queryOnlineUserInfo.getLoginedAdd())) {
                    onlineUserList.add(criteriaBuilder.like(root.get("loginedAdd") , "%" + queryOnlineUserInfo.getLoginedAdd() + "%"));
                }
                if (!org.springframework.util.StringUtils.isEmpty(queryOnlineUserInfo.getLoginedBrowser())) {
                    onlineUserList.add(criteriaBuilder.like(root.get("loginedBrowser") , "%" + queryOnlineUserInfo.getLoginedBrowser() + "%"));
                }
                if (queryOnlineUserInfo.getLoginedTime() != null) {
                    String loginedTime = DateTimeUtil.dateToStr(queryOnlineUserInfo.getLoginedTime(), "yyyy-MM-dd");
                    String loginedTimeStartTimeToStr = loginedTime + " " + "00:00:00";
                    String loginedTimeEndTimeToStr = loginedTime + " " + "23:59:59";
                    Date loginedTimeStartTimeToDate = DateTimeUtil.strToDate(loginedTimeStartTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    Date loginedTimeEndTimeToDate = DateTimeUtil.strToDate(loginedTimeEndTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    onlineUserList.add(criteriaBuilder.between(root.get("loginedTime") ,  loginedTimeStartTimeToDate , loginedTimeEndTimeToDate));
                }
                Order loginedTimeDesc = criteriaBuilder.desc(root.get("loginedTime"));
                return criteriaQuery.orderBy(loginedTimeDesc).where(onlineUserList.toArray(new Predicate[onlineUserList.size()])).getRestriction();
            }
        };
        Pageable pageable= PageRequest.of(page-1,limit);
        Page<OnlineUserInfo> onlineUserListPage  = onlineUserInfoDao.findAll(specification , pageable);
        if (onlineUserListPage!=null) {
            return new Result(0 , "在线用户分页数据获取成功" , new PageResult<OnlineUserInfo>(onlineUserListPage.getTotalElements(), onlineUserListPage.getContent()));
        }
        return new Result(201 , "返回在线用户列表失败");
    }

    @Override
    public Result forceLoginOut(String userId, HttpServletRequest request , HttpSession session) {
        User userFromSession = (User)session.getAttribute("admin");
        if (userFromSession == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        String id = userFromSession.getId();
        if (userId.equals(id)) {
            return new Result(202 , "不可强制本人下线");
        }
        try{
            jedisManager.del(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES+"::"+userId);
        }catch (Exception e) {
            return new Result(203 , "用户id: "+userId+"强制退出失败");
        }
        return new Result(200 , "用户id: "+userId+"强制退出成功");
    }

    @Override
    public Result isActive(HttpSession session) {
        User userFromSession = (User)session.getAttribute("admin");
        if (userFromSession == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        String userId = userFromSession.getId();
        Boolean isActive = jedisManager.exists(OnlineUserInfoInRedisConstant.OnlineUserInfo_RD_RESOURCES + "::" + userId);
        int code = isActive ? 201 : 200;
        String msg = code == 200 ? "会话过期" : "";
        return  new Result(code , msg);
    }
}
